<template>
  <div class="min-h-screen bg-gradient-to-br from-blue-50 to-purple-50 py-8">
    <div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
      <!-- Header -->
      <div class="text-center mb-8">
        <h1 class="text-3xl font-bold text-gray-900 mb-4">
          <span class="text-gradient">Base64编码转换</span>
        </h1>
        <p class="text-lg text-gray-600">
          文本与Base64编码相互转换
        </p>
      </div>

      <!-- Tool Container -->
      <div class="bg-white rounded-xl shadow-lg p-6">
        <!-- Mode Selection -->
        <div class="mb-6">
          <div class="flex space-x-4">
            <button
              @click="mode = 'encode'"
              :class="mode === 'encode' ? 'primary-button' : 'secondary-button'"
              class="flex-1"
            >
              编码 (文本 → Base64)
            </button>
            <button
              @click="mode = 'decode'"
              :class="mode === 'decode' ? 'primary-button' : 'secondary-button'"
              class="flex-1"
            >
              解码 (Base64 → 文本)
            </button>
          </div>
        </div>

        <!-- Input Area -->
        <div class="mb-6">
          <label class="block text-sm font-medium text-gray-700 mb-2">
            {{ mode === 'encode' ? '输入文本' : '输入Base64编码' }}
          </label>
          <textarea
            v-model="inputText"
            :placeholder="mode === 'encode' ? '请输入要编码的文本...' : '请输入要解码的Base64编码...'"
            class="textarea-field h-32"
            @input="performConversion"
          ></textarea>
          <div class="mt-2 text-sm text-gray-500">
            字符数: {{ inputText.length }}
          </div>
        </div>

        <!-- Output Area -->
        <div class="mb-6">
          <label class="block text-sm font-medium text-gray-700 mb-2">
            {{ mode === 'encode' ? 'Base64编码结果' : '解码后的文本' }}
          </label>
          <textarea
            v-model="outputText"
            readonly
            class="textarea-field h-32 bg-gray-50"
            :placeholder="mode === 'encode' ? 'Base64编码结果将显示在这里...' : '解码后的文本将显示在这里...'"
          ></textarea>
          <div class="mt-2 flex justify-between items-center">
            <span class="text-sm text-gray-500">
              字符数: {{ outputText.length }}
            </span>
            <button
              @click="copyToClipboard"
              class="secondary-button text-sm py-2 px-4"
              :disabled="!outputText"
            >
              {{ copied ? '已复制' : '复制结果' }}
            </button>
          </div>
        </div>

        <!-- Action Buttons -->
        <div class="flex flex-wrap gap-3">
          <button @click="performConversion" class="primary-button" :disabled="!inputText">
            {{ mode === 'encode' ? '编码' : '解码' }}
          </button>
          <button @click="clearAll" class="secondary-button">
            清空内容
          </button>
          <button @click="loadSample" class="secondary-button">
            加载示例
          </button>
        </div>

        <!-- Options and File Actions -->
        <div class="mt-4 flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3">
          <div class="flex items-center space-x-4">
            <label class="inline-flex items-center space-x-2 text-sm text-gray-700">
              <input type="checkbox" v-model="urlSafe" class="form-checkbox" />
              <span>URL-safe</span>
            </label>
            <label class="inline-flex items-center space-x-2 text-sm text-gray-700">
              <input type="checkbox" v-model="removePadding" class="form-checkbox" />
              <span>去除填充 (=)</span>
            </label>
          </div>

          <div class="flex items-center space-x-3">
            <button @click="triggerFileInput" class="secondary-button">
              从文件读取
            </button>
            <input ref="fileInputRef" type="file" class="hidden" @change="handleFileChange" />
            <button @click="downloadResult" class="secondary-button" :disabled="!outputText">
              下载结果
            </button>
          </div>
        </div>

        <!-- Error Message -->
        <div v-if="errorMessage" class="mt-4 p-3 bg-red-50 border border-red-200 rounded-lg">
          <p class="text-red-600 text-sm">{{ errorMessage }}</p>
        </div>
      </div>

      <!-- Instructions -->
      <div class="mt-8 bg-white rounded-xl shadow-lg p-6">
        <h3 class="text-lg font-semibold text-gray-900 mb-4">使用说明</h3>
        <ul class="space-y-2 text-gray-600">
          <li>• 选择编码或解码模式</li>
          <li>• 在上方文本框中输入内容</li>
          <li>• 系统会自动进行转换并显示结果</li>
          <li>• 使用"复制结果"按钮快速复制转换后的内容</li>
          <li>• Base64编码常用于数据传输和存储</li>
          <li>• 解码时请确保输入的是有效的Base64编码</li>
        </ul>
      </div>

      <!-- Technical Info -->
      <div class="mt-6 bg-white rounded-xl shadow-lg p-6">
        <h3 class="text-lg font-semibold text-gray-900 mb-4">技术说明</h3>
        <div class="text-gray-600 text-sm space-y-2">
          <p><strong>Base64是什么？</strong></p>
          <p>Base64是一种基于64个可打印字符来表示二进制数据的编码方式，常用于在HTTP协议、电子邮件等文本协议中传输二进制数据。</p>
          <p><strong>使用场景：</strong></p>
          <ul class="list-disc list-inside ml-4 space-y-1">
            <li>在HTML中嵌入图片数据</li>
            <li>在URL中传输二进制数据</li>
            <li>在JSON中存储二进制数据</li>
            <li>简单的数据加密（非安全加密）</li>
          </ul>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, watch } from 'vue'
import { useTools } from '@/composables/useTools'

const { copyToClipboard: toolsCopy, readFile, readImageFile, downloadFile } = useTools()

const mode = ref('encode') // 'encode' or 'decode'
const inputText = ref('')
const outputText = ref('')
const copied = ref(false)
const errorMessage = ref('')
const urlSafe = ref(false)
const removePadding = ref(false)
const fileInputRef = ref(null)

const performConversion = () => {
  errorMessage.value = ''
  
  if (!inputText.value.trim()) {
    outputText.value = ''
    return
  }

  try {
    if (mode.value === 'encode') {
      // 编码：文本 → Base64
      let b64 = toBase64Unicode(inputText.value)
      if (urlSafe.value) {
        b64 = b64.replace(/\+/g, '-').replace(/\//g, '_')
      }
      if (removePadding.value) {
        b64 = b64.replace(/=+$/g, '')
      }
      outputText.value = b64
    } else {
      // 解码：Base64 → 文本
      // 验证输入是否为有效的Base64
      if (!isValidBase64(inputText.value.trim())) {
        throw new Error('输入的不是有效的Base64编码')
      }
      // 处理 URL-safe（- _）并补齐
      let normalized = inputText.value.trim()
      normalized = normalized.replace(/-/g, '+').replace(/_/g, '/')
      // 补齐到4的倍数
      while (normalized.length % 4 !== 0) {
        normalized += '='
      }
      outputText.value = fromBase64Unicode(normalized)
    }
  } catch (error) {
    errorMessage.value = mode.value === 'encode' ? '编码失败：' + error.message : '解码失败：' + error.message
    outputText.value = ''
  }
}

const isValidBase64 = (str) => {
  try {
    const s = str.replace(/\s+/g, '')
    // URL-safe 变体允许 - 和 _，也允许去掉填充
    const base64Regex = /^[A-Za-z0-9+\/_=-]*$/
    if (!base64Regex.test(s)) return false
    // 尝试解码（先替换回标准）
    const normalized = s.replace(/-/g, '+').replace(/_/g, '/')
    atob(normalized.padEnd(Math.ceil(normalized.length / 4) * 4, '='))
    return true
  } catch (e) {
    return false
  }
}

const copyToClipboard = async () => {
  if (!outputText.value) return
  
  try {
    const ok = await toolsCopy(outputText.value)
    if (ok) {
      copied.value = true
      setTimeout(() => {
        copied.value = false
      }, 2000)
    } else {
    }
  } catch (err) {
  }
}

const clearAll = () => {
  inputText.value = ''
  outputText.value = ''
  errorMessage.value = ''
}

const loadSample = () => {
  if (mode.value === 'encode') {
    inputText.value = 'Hello, 世界! 这是一个Base64编码示例。'
  } else {
    inputText.value = 'SGVsbG8sIOS4lueVjCEg5L2g5pWw5o2uQmFzZTY05Yqg6L295ZCN56ewLg=='
  }
  performConversion()
}

const triggerFileInput = () => {
  if (fileInputRef.value) fileInputRef.value.click()
}

const handleFileChange = async (e) => {
  const file = e.target.files && e.target.files[0]
  if (!file) return
  errorMessage.value = ''
  try {
    // 如果是图片，使用 readImageFile 获取 dataUrl 否则读取为文本
    if (file.type.startsWith('image/')) {
      const { dataUrl } = await readImageFile(file)
      // dataUrl 格式: data:<mime>;base64,AAAA
      const parts = dataUrl.split(',')
      if (parts.length === 2) {
        // 将 base64 内容放到输入框以便编码/保存
        inputText.value = parts[1]
        if (mode.value === 'encode') {
          // 当用户想把文件转换为Base64时，直接显示base64
          performConversion()
        }
      }
    } else {
      const text = await readFile(file)
      // 如果是文本文件且是编码模式，把文本置入输入框
      inputText.value = text
      performConversion()
    }
  } catch (err) {
    errorMessage.value = '读取文件失败：' + err.message
  } finally {
    // reset
    e.target.value = ''
  }
}

const downloadResult = () => {
  if (!outputText.value) return
  const filename = mode.value === 'encode' ? 'base64.txt' : 'decoded.txt'
  downloadFile(outputText.value, filename, 'text/plain')
}

// UTF-8 安全的 base64 编码/解码
const toBase64Unicode = (str) => {
  const bytes = new TextEncoder().encode(str)
  let binary = ''
  for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i])
  return btoa(binary)
}

const fromBase64Unicode = (b64) => {
  const binary = atob(b64)
  const bytes = new Uint8Array(binary.length)
  for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i)
  return new TextDecoder().decode(bytes)
}

// 监听模式变化，清空内容
watch(mode, () => {
  clearAll()
})

// 监听输入变化，自动转换
watch(inputText, () => {
  performConversion()
})

// SEO
useHead({
  title: 'Base64编码转换 - 八八在线工具',
  meta: [
    { name: 'description', content: '在线Base64编码转换工具，支持文本编码和Base64解码，实时转换，无需注册' },
    { property: 'og:title', content: 'Base64编码转换 - 八八在线工具' },
    { property: 'og:description', content: '在线Base64编码转换工具，支持文本编码和Base64解码' }
  ]
})
</script>